package com.block.channel.flow.channel;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.block.channel.flow.IChannelReportService;
import com.block.channel.model.result.ReprotFlowResult;
import com.block.channel.service.monitor.VivoMonitorService;
import com.block.common.bean.CommonParam;
import com.block.common.constant.RedisKeyConstant;
import com.block.common.service.LogFactory;
import com.block.db.entity.ChannelBaseInfo;
import com.block.db.entity.SystemConstantInfo;
import com.block.db.mapper.ChannelActionMonitorRecordMapper;
import com.block.db.mapper.SystemConstantInfoMapper;
import lombok.Builder;
import lombok.Data;
import lombok.SneakyThrows;
import org.apache.commons.lang3.BitField;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * https://api.e.mi.com/doc.html#/1.0.0-mdtag9b26f-omd/document-f0283649125f62138db43c6f5fc25686
 *
 * 应用:
 * ID: 1599256名称: 臻享分期
 * 转化方案:
 * API上报方案
 * 秘钥A(encrypt_key):
 * icmQSYDXJROaHTpX
 * 秘钥B(sign_key):
 * YLLiCGeXPcUPCLJB
 *
 */

@Service
public class XiaoMiChannelReportService implements IChannelReportService {

    private static Logger log = LogFactory.getCommLog();

    public static Long APP_ID = Long.valueOf("1599256");
    public static String ENCRYPT_KEY = "icmQSYDXJROaHTpX";
    public static String SIGN_KEY = "YLLiCGeXPcUPCLJB";

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Override
    public ReprotFlowResult registerActionReport(CommonParam commonParam, ChannelBaseInfo channelBaseInfo) {

        ReprotFlowResult flowResult = new ReprotFlowResult();
        flowResult.setSuccess(false);

        JSONObject headObject = commonParam.getHeadObject();

        String OAID = headObject.getString("originparm1");
        String IMEI_MD5 = headObject.getString("originparm2");

        if (StrUtil.isEmpty(OAID)) {
            flowResult.setCode("-2");
            flowResult.setMessage("OAID和IMEI_MD5参数为空，不做处理");
            return flowResult;
        }

//        String token = this.getToken();
//        if (StrUtil.isEmpty(token)) {
//            flowResult.setCode("-2");
//            flowResult.setMessage("获取token为空");
//            return flowResult;
//        }

        //
//        ChannelActionMonitorRecord monitorRecord = channelActionMonitorRecordMapper.queryEntityByUnikeyAndActionType(OAID, "CLICK", channelBaseInfo.getChannelCode());
//        if (ObjectUtil.isEmpty(monitorRecord)) {
//            flowResult.setCode("-2");
//            flowResult.setMessage("可上报信息为空");
//            return flowResult;
//        }

        String conv_type = "APP_REGISTER";
        Integer customer_id = Integer.valueOf(689442);
        Long actionTime = System.currentTimeMillis();

        UploadInfo uploadInfo = UploadInfo.builder()
//                .imei(imei)
                .oaid(OAID)
//                .ua(ua)
                .clientIp(commonParam.getReqIp())
                .convTime(actionTime)
                .convType(conv_type)
                .appId(APP_ID)
                .customerId(customer_id)
                .signKey(SIGN_KEY)
                .encryptKey(ENCRYPT_KEY)
                .build().genInfo();

        String reqUrl = uploadInfo.getFinalUrl();

        log.info("【小米信息流上报】【注册】【开始请求】【reqestUrl】{}", reqUrl);
        String response = HttpUtil.createGet(reqUrl)
                .execute().body();
        log.info("【小米信息流上报】【注册】【开始结束】【result】{}", response);

        JSONObject resultObject = JSONObject.parseObject(response);
        Integer code = resultObject.getInteger("code");
        String message = resultObject.getString("message");

        flowResult.setCode(String.valueOf(code));
        flowResult.setMessage(message);
        flowResult.setParamInfo(reqUrl);
        flowResult.setResultInfo(response);
        if (ObjectUtil.equals(code, Integer.valueOf(1))){
            flowResult.setSuccess(true);
        }else{
            flowResult.setSuccess(false);
        }

        return flowResult;
    }
    @Override
    public ReprotFlowResult sourceActionReport(CommonParam commonParam, ChannelBaseInfo channelBaseInfo) {
        return null;
    }
    @Override
    public ReprotFlowResult downloadActionReport(CommonParam commonParam, ChannelBaseInfo channelBaseInfo) {
        return null;
    }

    @Override
    public ReprotFlowResult payBuyActionReport(CommonParam commonParam, ChannelBaseInfo channelBaseInfo) {
        return null;
    }

    @Data
    @Builder
    public static class UploadInfo {
        //info设备信息
        private String imei;
        private String oaid;
        private long convTime;
        private String clientIp;
        private String ua;
        private long adId;
        //conversion转化信息
        private long appId;
        private int customerId;
        private String convType;
        private String signKey;
        private String encryptKey;
        //生成的信息
        //最终url
        private String finalUrl;
        //最终生成的info
        private String finalInfo;
        //queryString 设备信息
        private String queryString;
        private String property;
        private String baseData;
        //md5后的sign值
        private String signature;

        private final static String HOST = "http://trail.e.mi.com";
//        private final static String PATH = "/global/test";
        private final static String PATH = "/global/log";

        @SneakyThrows
        public UploadInfo genInfo() {
            List<String> kvParam = new ArrayList<>();
            if (StringUtils.isNotBlank(this.imei)) {
                kvParam.add("imei=" + URLEncoder.encode(this.imei, "UTF-8"));
            }
            if (StringUtils.isNotBlank(this.oaid)) {
                kvParam.add("oaid=" + URLEncoder.encode(this.oaid, "UTF-8"));
            }
            if (this.convTime > 0) {
                kvParam.add("conv_time=" + URLEncoder.encode(String.valueOf(this.convTime), "UTF-8"));
            }
            if (StringUtils.isNotBlank(this.clientIp)) {
                kvParam.add("client_ip=" + URLEncoder.encode(this.clientIp, "UTF-8"));
            }
            if (StringUtils.isNotBlank(this.ua)) {
                kvParam.add("ua=" + URLEncoder.encode(this.ua, "UTF-8"));
            }
            if (this.adId > 0) {
                kvParam.add("ad_id=" + URLEncoder.encode(String.valueOf(this.adId), "UTF-8"));
            }

            try {
                //1.按照顺序使用 & 拼接key=urlEncode(value),queryString
                this.queryString = String.join("&", kvParam);
                //2.按照顺序使用 & 拼接签名密钥signKey 和 urlEncode(queryString),得到property
                this.property = this.signKey + "&" + URLEncoder.encode(this.queryString, "UTF-8");
                //3. 将字符串(property) 进行md5(property)加密,得到32位小写字符串signature
                this.signature = getMd5Digest(this.property);
            } catch (Exception ignored) {

            }
            //4.按照顺序使用 & 拼接 queryString(注意是第一个步骤生成的) 和 sign=signature
            this.baseData = this.queryString + "&sign=" + this.signature;
            //5.baseData进行加密 Base64(simple_xor{base_data, encrypt_key}),得到info信息
            this.finalInfo = encrypt(this.baseData, this.encryptKey);
            this.finalUrl = HOST + PATH
                    + "?appId=" + URLEncoder.encode(String.valueOf(this.appId), "UTF-8")
                    + "&info=" + URLEncoder.encode(this.finalInfo, "UTF-8")
                    + "&conv_type=" + URLEncoder.encode(this.convType, "UTF-8")
                    + "&customer_id=" + URLEncoder.encode(String.valueOf(this.customerId), "UTF-8");

            return this;
        }

        //对baseData进行加密 Base64(simple_xor{base_data, encrypt_key})
        public static String encrypt(String info, String key) {
            try {
                if (StringUtils.isEmpty(info) || StringUtils.isEmpty(key)) {
                    return null;
                }
                //6.1 base_data, encrypt_key 异或加密
                char[] infoChar = info.toCharArray();
                char[] keyChar = key.toCharArray();

                byte[] resultChar = new byte[infoChar.length];
                for (int i = 0; i < infoChar.length; i++) {
                    resultChar[i] = (byte) ((infoChar[i] ^ keyChar[i % keyChar.length]) & 0xFF);
                }
                //6.2 Base64 编码
                return Base64.encode(resultChar);
            } catch (Exception e) {
                return null;
            }
        }

        //md5 加密得到32位小写字符串.
        public static String getMd5Digest(String pInput) {
            try {
                MessageDigest lDigest = MessageDigest.getInstance("MD5");
                lDigest.update(pInput.getBytes("UTF-8"));
                BigInteger lHashInt = new BigInteger(1, lDigest.digest());
                return String.format("%1$032x", lHashInt);
            } catch (Exception e) {

            }
            return "";
        }
    }

}
